package com.squid.search.service.document;

import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.function.BiConsumer;

/**
 * Description
 *
 * @author jinhang
 * @since 2024-2-23
 **/

@Service
@Slf4j
public class DocumentServiceImpl implements DocumentService {
    @Resource
    private ElasticsearchClient elasticsearchClient;

    @Resource
    private ElasticsearchAsyncClient elasticsearchAsyncClient;

    @Override
    public IndexResponse createByFluentDSL(String idxName, String idxId, Object document) {
        try {
            IndexResponse response = elasticsearchClient.index(idx -> idx
                    .index(idxName)
                    .id(idxId)
                    .document(document));
            return response;
        } catch (IOException e) {
            log.error("创建文档失败");
            throw new RuntimeException("创建文档失败");
        }
    }

    @Override
    public IndexResponse createByBuilderPattern(String idxName, String idxId, Object document) {
        IndexRequest.Builder<Object> indexReqBuilder = new IndexRequest.Builder<>();

        indexReqBuilder.index(idxName);
        indexReqBuilder.id(idxId);
        indexReqBuilder.document(document);
        try {
            return elasticsearchClient.index(indexReqBuilder.build());
        } catch (IOException e) {
            log.error("创建文档失败");
            throw new RuntimeException("创建文档失败");
        }
    }

    @Override
    public IndexResponse createByJson(String idxName, String idxId, String jsonContent) {
        try {
            return elasticsearchClient.index(i -> i
                    .index(idxName)
                    .id(idxId)
                    .withJson(new StringReader(jsonContent))
            );
        } catch (IOException e) {
            log.error("创建文档失败");
            throw new RuntimeException("创建文档失败");
        }
    }

    @Override
    public void createAsync(String idxName, String idxId, Object document, BiConsumer<IndexResponse, Throwable> action) {
        try {
            elasticsearchAsyncClient.index(idx -> idx
                    .index(idxName)
                    .id(idxId)
                    .document(document)
            ).whenComplete(action);
        } catch (Exception e) {
            log.error("创建文档失败");
            throw new RuntimeException("创建文档失败");
        }
    }

    @Override
    public BulkResponse bulkCreate(String idxName, List<Object> documents) {
        BulkRequest.Builder br = new BulkRequest.Builder();

        // TODO 可以将 Object定义为一个文档基类。比如 ESDocument类

        // 将每一个product对象都放入builder中
        //documents.stream()
        //        .forEach(esDocument -> br
        //                .operations(op -> op
        //                        .index(idx -> idx
        //                                .index(idxName)
        //                                .id(esDocument.getId())
        //                                .document(esDocument))));

        try {
            return elasticsearchClient.bulk(br.build());
        } catch (IOException e) {
            log.error("创建文档失败");
            throw new RuntimeException("创建文档失败");
        }
    }

    @Override
    public Object getById(String idxName, String docId) {
        try {
            GetResponse<Object> response = elasticsearchClient.get(g -> g
                            .index(idxName)
                            .id(docId),
                    Object.class);
            return response.found() ? response.source() : null;
        } catch (IOException e) {
            log.error("获取文档失败");
            throw new RuntimeException("获取文档失败");
        }
    }

    @Override
    public ObjectNode getObjectNodeById(String idxName, String docId) {
        try {
            GetResponse<ObjectNode> response = elasticsearchClient.get(g -> g
                            .index(idxName)
                            .id(docId),
                    ObjectNode.class);

            return response.found() ? response.source() : null;
        } catch (IOException e) {
            log.error("获取文档失败");
            throw new RuntimeException("获取文档失败");
        }
    }

    @Override
    public Boolean deleteById(String idxName, String docId) {
        try {
            DeleteResponse delete = elasticsearchClient.delete(d -> d
                    .index(idxName)
                    .id(docId));
            return delete.forcedRefresh();
        } catch (IOException e) {
            log.error("删除文档失败");
            throw new RuntimeException("删除文档失败");
        }
    }

    @Override
    public BulkResponse bulkDeleteByIds(String idxName, List<String> docIds) {
        BulkRequest.Builder br = new BulkRequest.Builder();

        // 将每一个对象都放入builder中
        docIds.forEach(id -> br
                .operations(op -> op
                        .delete(d -> d
                                .index(idxName)
                                .id(id))));

        try {
            return elasticsearchClient.bulk(br.build());
        } catch (IOException e) {
            log.error("删除文档失败");
            throw new RuntimeException("删除文档失败");
        }
    }

    public void selectAll() {
    }
}
